// $codepro.audit.disable lossOfPrecisionInCast, numericLiterals, expressionValue, packagePrefixNamingConvention
/**
 * presentation package
 */
package javamonsters.universe.presentation;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Ellipse2D;
import java.util.List;

import javamonsters.model.Ship;
import javamonsters.model.SolarSystem;
import javamonsters.universe.application.UniverseController;
import javamonsters.universe.presentation.interfaces.UniverseView;
import javamonsters.view.SpaceTraders;

import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;


/**
 * The Class UniverseView displays a Universe.
 * 
 * @author wa
 * @version 1.0
 */

public class DefaultUniverseView extends JPanel implements UniverseView {
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 4435575533631621194L;

	/**
	 * Parent controller for callbacks.
	 */

	private UniverseController controller;
	
	/**
	 * Travel radius
	 */

	private Ellipse2D circle;

	/**
	 * Keeps track of which system a user is considering.
	 */

	private SolarSystem selectedSystem;
	
	/**
	 * The solar systems within the universe.
	 */
	private List<SolarSystem> systems;
	
	/**
	 * half the system icon width
	 */
	private final float halfIconWidth;
	
	/**
	 * half the system icon height
	 */
	private final float halfIconHeight;
	
	/**
	 * number to divide fuel by to find distance 
	 */
	private final double fuelDivider;
	
	/**
	 * integer adjusters to make the circle around the icon
	 */
	private final int currentLocationAdjusterX, currentLocationAdjusterY;
	
	/**
	 * size of the circle to be drawn around current system
	 */
	private final int currentLocationCircleSize;
	
	/**
	 * integer adjuster so that the circle that represents the distance the player
	 * can travel is drawn correctly
	 */
	private final int reachableCircleAdjuster;
	
	/**
	 * Instantiates a new universe view.
	 */
	public DefaultUniverseView() {
		halfIconWidth = 7.5f;
		halfIconHeight = 7.5f;
		fuelDivider = 5.0;
		currentLocationAdjusterX = 3;
		currentLocationAdjusterY = 3;
		currentLocationCircleSize = 20;
		reachableCircleAdjuster = 5;
		super.setPreferredSize(new Dimension(350, 380));
		super.setBackground(Color.black);
		super.setLayout(null);
	}
	
	/**
	 * Populates the collection of SolarSystems so they can be painted.
	 *
	 * @param solarSystems the solar systems to be painted.
	 */
	@Override
	public void plotSystems(List<SolarSystem> solarSystems) {
		removeAll();
		this.systems = solarSystems;
		final ImageIcon ssIcon = new ImageIcon("graphics/Galaxy.gif");
		for (final SolarSystem ss : systems) {
			Point coordinates = ss.getCoordinates();
			System.out.println(coordinates);
			JLabel ssLabel = new JLabel(ssIcon);
			ssLabel.setBounds(coordinates.x, coordinates.y, 
					ssIcon.getIconWidth(), ssIcon.getIconHeight());
			ssLabel.addMouseListener(new MouseAdapter() {
				
				@Override
				//loads system when user releases mouse click
				public void mouseReleased(MouseEvent arg0) {
					selectedSystem = ss;
					controller.getSideView().getSystemLabel().setText(ss.getName());
					controller.getSideView().getTechLevelLabel().setText(
							ss.getTechLevel().toString());
					controller.getSideView().getAttributeLabel().setText(
							ss.getAttributes().toString());
					final SpaceTraders spaceTraders = controller.getController();
					int fuel = spaceTraders.getPlayer().getShip().getFuel();
					controller.getSideView().getCurrentFuelLabel().setText("" + fuel);
					Point startLocation = controller.getController()
							.getPlayer().getCurrLocation();
					Point destLocation = ss.getCoordinates();
					
					int distance = (int) Math.sqrt(Math.pow(startLocation.x - 
							destLocation.x, 2) + Math.pow(
									startLocation.y - destLocation.y, 2)); 
					distance /= fuelDivider;
					
					controller.getSideView().getFuelCostLabel().setText("" + distance);
					if (!circle.contains(ss.getCoordinates().x + halfIconWidth,
							ss.getCoordinates().y + halfIconHeight)) {
						controller.getSideView().getTravelButton().setEnabled(false);
					} else {
						controller.getSideView().getTravelButton().setEnabled(true);
					}
				}
			});
			add(ssLabel);
		}
		repaint();
	}
	
	/**
	 * @param g the graphics object used to paint various things
	 */
	@Override
	public void paintComponent(Graphics g) {
		//draws white circle around reachable systems, draws red circle around current system
		final Graphics2D g2 = (Graphics2D) g;
		super.paintComponent(g);
		g.setColor(Color.white);
		final int xPos = controller.getController().getPlayer().getCurrLocation().x;
		final int yPos = controller.getController().getPlayer().getCurrLocation().y;
		final Ship ship = controller.getController().getPlayer().getShip();
		circle = new Ellipse2D.Float(
				xPos - reachableCircleAdjuster * ship.getFuel() + halfIconWidth,
				yPos - reachableCircleAdjuster * ship.getFuel()
				+ halfIconHeight,
				2 * reachableCircleAdjuster * ship.getFuel(),
				2 * reachableCircleAdjuster * ship.getFuel());
		g2.draw(circle);
		g.setColor(Color.red);
		g.drawOval(xPos - currentLocationAdjusterX, yPos - currentLocationAdjusterY,
				   currentLocationCircleSize, currentLocationCircleSize);
		//display info to the right of the map
		
		
	}
	
	/**
	 * sets the controller for the view
	 * 
	 * @param universeController the new universe controller to be set
	 */
	@Override
	public void setController(UniverseController universeController) {
		this.controller = universeController;
	}
	
	/**
	 * @return the UniverseController for the view
	 */
	public UniverseController getController() {
		return controller;
	}
	
	/**
	 * @return the circle that represents how far the player can travel
	 */
	public Ellipse2D getCircle() {
		return circle;
	}
	
	/**
	 * @return the currently selected system
	 */
	public SolarSystem getSelectedSystem() {
		return selectedSystem;
	}
}
